import javax.microedition.lcdui.Graphics;
import java.io.DataInputStream;
import java.io.IOException;

public final class LevObj {
    public byte nClassID = 0;
    public short m_nPosX = 0;
    public short m_nPosY = 0;
    public short m_nParam = 0;
    public short m_nAddParam = 0;

    public short objPosX, objPosY;
    public byte objStepX, objStepY;
    public byte objState;
    private int tickCounter;

    public Animation animationCurrent = null;
    public Animation[] animationList;

    public boolean m_blActive;

    public static final byte c_bCannonState_Charging   = 0;
    public static final byte c_bCannonState_ClimbIn    = 1;
    public static final byte c_bCannonState_Move       = 2;
    public static final byte c_bCannonState_Aiming     = 3;
    public static final byte c_bCannonState_Fire       = 4;
    public static final byte c_bCannonState_ClimbOut   = 5;

    public static final short c_shBonusXLife           = 0;
    public static final short c_shBonusDynamite        = -1;
    public static final short c_shBonusPickAxe         = -2;

    public static byte teleportCount = 0;

    //#if USE_GAME_TIPS
    private MTMCanvas canv = null;

    public void Init(int index, int n_clsid, short x, short y, DataInputStream dis, MTMCanvas canv) throws IOException {
        this.canv = canv;
    //#else
    public void Init(int index, int n_clsid, short x, short y, DataInputStream dis) throws IOException {
    //#endif
        nClassID = (byte)n_clsid;
        m_nPosX = x;
        m_nPosY = y;
        m_blActive = true;

        switch (n_clsid) {
            case ObjID.nObjID_CrashingPlatform:
                animationCurrent = new Animation(AnimID.AnimID_CrashingPlatform);
                tickCounter = 0;

                objPosX = m_nPosX;
                objPosY = m_nPosY;

                objState = Constants.CRASHING_PLATFORM_STATE_WAIT;
            break;

            case ObjID.nObjID_Spring:
                animationCurrent = new Animation(AnimID.AnimID_Spring);
                m_blActive = false;
                m_nParam = 0;
            break;

            case ObjID.nObjID_Firewall:
                animationList = new Animation[3];
                animationList[Constants.ANIMATION_FIREWALL_START_FINISH] = new Animation(AnimID.AnimID_FirewallStartFinish);
                animationList[Constants.ANIMATION_FIREWALL] = new Animation(AnimID.AnimID_Firewall);
                animationList[Constants.ANIMATION_FIREWALL_IDLE] = new Animation(AnimID.AnimID_FirewallIdle);
                animationList[Constants.ANIMATION_FIREWALL_IDLE].setLayerProperty(0, 0, Constants.LAYERPROPERTY_VISIBLE, 0);

                if (dis != null) {
                    m_nParam = dis.readByte();
                }

                animationCurrent = animationList[Constants.ANIMATION_FIREWALL_START_FINISH];
                m_nAddParam = ( short ) (3 + FP.abs(( GameWorld.rnd.nextInt() & 3 )));
                m_blActive = true;
            break;

            case ObjID.nObjID_Cannon:
                animationList = new Animation[3];
                animationList[Constants.ANIMATION_CANNON] = new Animation(AnimID.AnimID_Cannon);
                animationList[Constants.ANIMATION_CANNON_FIRE] = new Animation(AnimID.AnimID_CannonFire);
                animationList[Constants.ANIMATION_CANNON_CLIMB] = new Animation(AnimID.AnimID_ClimbCannon);

                animationCurrent = animationList[Constants.ANIMATION_CANNON];
                m_blActive = false;
            break;

            case ObjID.nObjID_Teleport:
                if (dis != null) {
                    boolean flag = dis.readBoolean();
                    m_nParam = flag ? (short)0 : (short)1; // random?
                    m_nParam |= (index << 8) & 0xFF00;
                }
                animationCurrent = new Animation(AnimID.AnimID_Teleport);
            break;

            case ObjID.nObjID_Transporter45Degree:
                if (dis != null) {
                    m_nAddParam = dis.readShort(); // ladders bottom or transporter position
                }
            case ObjID.nObjID_TransporterHorz:
            case ObjID.nObjID_TransporterVert:
                if (dis != null) {
                    m_nParam = dis.readShort(); // ladders bottom or transporter position
                }
                animationCurrent = new Animation(AnimID.AnimID_Transporter);
                objState = Constants.TRANSPORTER_STATE_WAIT;
                tickCounter = 0;
                objPosX = m_nPosX;
                objPosY = m_nPosY;
                switch (nClassID) {
                    case ObjID.nObjID_TransporterHorz:
                        if (m_nPosX > m_nParam) {
                            objStepX = Constants.TRANSPORTER_STEP_X;
                        }
                        else {
                            objStepX = -Constants.TRANSPORTER_STEP_X;
                        }
                        objStepY = 0;
                    break;

                    case ObjID.nObjID_TransporterVert:
                        objStepX = 0;
                        if (m_nPosY > m_nParam) {
                            objStepY = Constants.TRANSPORTER_STEP_Y;
                        }
                        else {
                            objStepY = -Constants.TRANSPORTER_STEP_Y;
                        }
                    break;

                    case ObjID.nObjID_Transporter45Degree:
                        if (m_nPosX > m_nAddParam) {
                            objStepX = Constants.TRANSPORTER_STEP_X;
                        }
                        else {
                            objStepX = -Constants.TRANSPORTER_STEP_X;
                        }

                        if (m_nPosY > m_nParam) {
                            objStepY = Constants.TRANSPORTER_STEP_Y;

                            // replace start point and end point
                            short tmp = m_nPosX;
                            m_nPosX = m_nAddParam;
                            m_nAddParam = tmp;

                            tmp = m_nPosY;
                            m_nPosY = m_nParam;
                            m_nParam = tmp;
                        }
                        else {
                            objStepY = -Constants.TRANSPORTER_STEP_Y;
                        }
                    break;
                }
            break;

            case ObjID.nObjID_Ladder:
                if (dis != null) {
                    m_nParam = dis.readShort(); // ladders bottom or transporter position
                }
                m_blActive = false;
            break;

            case ObjID.nObjID_Slide:
                if (dis != null) {
                    m_nAddParam = dis.readShort();
                    m_nParam = dis.readShort();
                }
            break;

            case ObjID.nObjID_Bonus1:
                nClassID = (byte)ObjID.nObjID_Bonus;
                m_nParam = Constants.SCORE_DIAMOND_1;
                animationCurrent = new Animation(AnimID.AnimID_Bonus1);
            break;

            case ObjID.nObjID_Bonus2:
                nClassID = (byte)ObjID.nObjID_Bonus;
                m_nParam = Constants.SCORE_DIAMOND_2;
                animationCurrent = new Animation(AnimID.AnimID_Bonus2);
            break;

            case ObjID.nObjID_Bonus3:
                nClassID = (byte)ObjID.nObjID_Bonus;
                m_nParam = Constants.SCORE_DIAMOND_3;
                animationCurrent = new Animation(AnimID.AnimID_Bonus3);
            break;

            case ObjID.nObjID_Bonus4:
                nClassID = (byte)ObjID.nObjID_Bonus;
                m_nParam = Constants.SCORE_DIAMOND_4;
                animationCurrent = new Animation(AnimID.AnimID_Bonus4);
            break;

            case ObjID.nObjID_Bonus5:
                nClassID = (byte)ObjID.nObjID_Bonus;
                m_nParam = Constants.SCORE_DIAMOND_5;
                animationCurrent = new Animation(AnimID.AnimID_Bonus5);
            break;

            case ObjID.nObjID_BonusLife:
                nClassID = (byte)ObjID.nObjID_Bonus;
                m_nParam = c_shBonusXLife;
                animationCurrent = new Animation(AnimID.AnimID_BonusLife);
            break;

            case ObjID.nObjID_BonusDynamite:
                nClassID = (byte)ObjID.nObjID_Bonus;
                m_nParam = c_shBonusDynamite;
                animationCurrent = new Animation(AnimID.AnimID_BonusDynamite);
            break;

            case ObjID.nObjID_BonusPickAxe:
                nClassID = (byte)ObjID.nObjID_Bonus;
                m_nParam = c_shBonusPickAxe;
                animationCurrent = new Animation(AnimID.AnimID_BonusPickAxe);
            break;

            //#if !(IMGGROUP_12x12xLimited || IMGGROUP_24x24xLimited)
                case ObjID.nObjID_DynCount + DecID.nDecID_Torch:
                    animationCurrent = new Animation(AnimID.AnimID_Torch);
                break;
            //#endif
        }
    }

    /**
     *
     */
    public int Tick(byte b_tick) {
        //#if USE_GAME_TIPS
            boolean flag = (GameMenu.isGameTipsOn()) && (Hero.m_nDeathTicks == 0) &&
                           (MTMCanvas.nCurrentGameState != MTMCanvas.GAME_STATE_SHOW_TIP) &&
                           (m_nPosX > (Hero.m_nPosX - Constants.TIP_START_DISTANCE)) && (m_nPosY > (Hero.m_nPosY - Hero.animationCurrent.GetCurFrmHeight() - Constants.TIP_START_DISTANCE)) &&
                           (m_nPosX < (Hero.m_nPosX + Constants.TIP_START_DISTANCE)) && (m_nPosY < (Hero.m_nPosY + Constants.TIP_START_DISTANCE));
        //#endif

        switch (nClassID) {
            case ObjID.nObjID_CrashingPlatform: {
                switch (objState) {
                    case Constants.CRASHING_PLATFORM_STATE_MARV_STEP:
                        tickCounter++;
                        if (tickCounter > Constants.CRASHING_PLATFORM_WAIT_TICKS) {
                            tickCounter = Constants.CRASHING_PLATFORM_WAIT_TICKS;
                            objState = Constants.CRASHING_PLATFORM_STATE_FALL;
                            animationCurrent.Tick();
                            objStepY = Constants.CRASHING_PLATFORM_STEP_INC << 1;
                        }
                    break;

                    case Constants.CRASHING_PLATFORM_STATE_FALL:
                        objPosY += objStepY / Constants.CRASHING_PLATFORM_STEP_DIV;
                        objStepY += Constants.CRASHING_PLATFORM_STEP_INC;
                    break;

                    case Constants.CRASHING_PLATFORM_STATE_SLOW_DOWN:
                        if (objStepY >= 0) {
                            objPosY += objStepY / Constants.CRASHING_PLATFORM_STEP_DIV;
                     
                            if ((Constants.CRASHING_PLATFORM_STEP_INC & 1) == 0) {
                                objStepY -= (Constants.CRASHING_PLATFORM_STEP_INC >> 1) - 1;
                            }
                            else {
                                objStepY -= Constants.CRASHING_PLATFORM_STEP_INC >> 1;
                            }
                        }
                        else {
                            if ((Constants.CRASHING_PLATFORM_STEP_INC & 1) == 0) {
                                objStepY = -(Constants.CRASHING_PLATFORM_STEP_INC >> 1);
                            }
                            else {
                                objStepY = -((Constants.CRASHING_PLATFORM_STEP_INC >> 1) + 1);
                            }
                            objState = Constants.CRASHING_PLATFORM_STATE_CLIMB;
                        }
                    break;

                    case Constants.CRASHING_PLATFORM_STATE_CLIMB:
                        if (objPosY <= m_nPosY) {
                            objPosY = m_nPosY;
                            objState = Constants.CRASHING_PLATFORM_STATE_WAIT;
                            tickCounter = 0;
                        }
                        else {
                            objPosY += objStepY;
                        }
                    break;
                }

                //#if USE_GAME_TIPS
                    if ((GameMenu.isGameTipsOn()) && (Hero.m_nDeathTicks == 0) &&
                        (MTMCanvas.nCurrentGameState != MTMCanvas.GAME_STATE_SHOW_TIP) &&
                        (m_nPosX > (Hero.m_nPosX - ( 5 * Constants.TIP_START_DISTANCE >> 1))) && (m_nPosY > (Hero.m_nPosY - Hero.animationCurrent.GetCurFrmHeight() - Constants.TIP_START_DISTANCE)) &&
                        (m_nPosX < (Hero.m_nPosX + ( 5 * Constants.TIP_START_DISTANCE >> 1))) && (m_nPosY < (Hero.m_nPosY + Constants.TIP_START_DISTANCE)) &&
                        (Hero.m_nLevel <= GameWorld.gameTips[Constants.TIP_CRASHING_PLATFORM])) {
                        
                        Hero.m_nSpeed45Degree = 0;
                        GameWorld.gameTips[Constants.TIP_CRASHING_PLATFORM] = -1;
                        MTMCanvas.resetKeys();
                        GameMenu.strToText(StringsID.nStrID_TipCrashingPlatform, true);
                        MTMCanvas.nCurrentGameState = MTMCanvas.GAME_STATE_SHOW_TIP;
                        GameMenu.Init(canv);
                    }
                //#endif
            }
            break;

            case ObjID.nObjID_TransporterHorz:
            case ObjID.nObjID_TransporterVert:
            case ObjID.nObjID_Transporter45Degree:
                animationCurrent.Tick();
                switch (objState) {
                    case Constants.TRANSPORTER_STATE_WAIT:
                        tickCounter++;
                        if (tickCounter > Constants.TRANSPORTER_WAIT_TICKS) {
                            tickCounter = 0;
                            objState = Constants.TRANSPORTER_STATE_MOVE;
                            switch (nClassID) {
                                case ObjID.nObjID_TransporterHorz:
                                    objStepX *= -1;
                                break;
                                
                                case ObjID.nObjID_TransporterVert:
                                    objStepY *= -1;
                                break;

                                case ObjID.nObjID_Transporter45Degree:
                                    objStepX *= -1;
                                    objStepY *= -1;
                                break;
                            }
                        }
                    break;

                    case Constants.TRANSPORTER_STATE_MOVE:
                        objPosX += objStepX;
                        objPosY += objStepY;
                        switch (nClassID) {
                            case ObjID.nObjID_TransporterHorz:
                                if (m_nPosX < m_nParam) {
                                    if (objPosX <= m_nPosX) {
                                        objPosX = m_nPosX;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                    else if (objPosX >= m_nParam) {
                                        objPosX = m_nParam;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                }
                                else if (m_nPosX > m_nParam) {
                                    if (objPosX <= m_nParam) {
                                        objPosX = m_nParam;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                    else if(objPosX >= m_nPosX) {
                                        objPosX = m_nPosX;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                }
                            break;

                            case ObjID.nObjID_TransporterVert:
                                if (m_nPosY < m_nParam) {
                                    if (objPosY >= m_nParam) {
                                        objPosY = m_nParam;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                    else if(objPosY <= m_nPosY) {
                                        objPosY = m_nPosY;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                }
                                else if(m_nPosY > m_nParam) {
                                    if (objPosY >= m_nPosY) {
                                        objPosY = m_nPosY;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                    else if (objPosY <= m_nParam) {
                                        objPosY = m_nParam;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                }
                            break;

                            case ObjID.nObjID_Transporter45Degree:
                                if (m_nPosX < m_nAddParam && m_nPosY < m_nParam) { // left,top -> right,bot
                                    if ((objPosX < m_nPosX) || (objPosY < m_nPosY)) {
                                        objPosX = m_nPosX;
                                        objPosY = m_nPosY;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                    else if ((objPosX > m_nAddParam) || (objPosY > m_nParam)) {
                                        objPosX = m_nAddParam;
                                        objPosY = m_nParam;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                }
                                else if (m_nPosX > m_nAddParam && m_nPosY < m_nParam) { // right,top -> left,bot
                                    if ((objPosX > m_nPosX) || (objPosY < m_nPosY)) {
                                        objPosX = m_nPosX;
                                        objPosY = m_nPosY;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                    else if ((objPosX < m_nAddParam) || (objPosY > m_nParam)) {
                                        objPosX = m_nAddParam;
                                        objPosY = m_nParam;
                                        objState = Constants.TRANSPORTER_STATE_WAIT;
                                    }
                                }
                            break;
                        }
                    break;
                }
            break;

            case ObjID.nObjID_Bonus:
                if (m_blActive) {
                    animationCurrent.Tick();

                    //#if USE_GAME_TIPS
                        if (flag) {
                            if ((m_nParam == c_shBonusDynamite) && (Hero.m_nLevel <= GameWorld.gameTips[Constants.TIP_DYNAMITE])) {
                                GameWorld.gameTips[Constants.TIP_DYNAMITE] = -1;

                                MTMCanvas.resetKeys();
                                GameMenu.strToText(StringsID.nStrID_TipDynamite, true);
                                MTMCanvas.nCurrentGameState = MTMCanvas.GAME_STATE_SHOW_TIP;
                                GameMenu.Init(canv);
                            }
                            else if((m_nParam == c_shBonusPickAxe) && (Hero.m_nLevel <= GameWorld.gameTips[Constants.TIP_PICKAXE])) {
                                GameWorld.gameTips[Constants.TIP_PICKAXE] = -1;

                                MTMCanvas.resetKeys();
                                GameMenu.strToText(StringsID.nStrID_TipPickaxe, true);
                                MTMCanvas.nCurrentGameState = MTMCanvas.GAME_STATE_SHOW_TIP;
                                GameMenu.Init(canv);
                            }
                        }
                    //#endif
                }
            break;

            case ObjID.nObjID_Firewall: {
                animationCurrent.Tick();

                if (m_blActive) {
                    if ((animationCurrent.nStateFlg & Animation.cnANIM_STATE_END_OF_CYCLE) != 0) {
                        if ( m_nAddParam <= 2 ) {
                            animationCurrent = animationList[Constants.ANIMATION_FIREWALL_START_FINISH];
                        }
                        else {
                            animationCurrent = animationList[Constants.ANIMATION_FIREWALL];
                        }
                        animationCurrent.Reset();
                        m_nAddParam--;
                    }
                }
                else {
                    if ((animationCurrent.nStateFlg & Animation.cnANIM_STATE_END_OF_CYCLE) != 0) {
                        animationCurrent.Reset();
                    }
                    m_nAddParam--;
                }

                if ( m_nAddParam <= 0 ) {
                    m_blActive = !m_blActive;
                    if ( m_blActive ) {
                        animationCurrent = animationList[Constants.ANIMATION_FIREWALL_START_FINISH];
                        animationCurrent.Reset();
                        m_nAddParam = ( short ) (3 + FP.abs(( GameWorld.rnd.nextInt() & 3 )));
                    }
                    else {
                        animationCurrent = animationList[Constants.ANIMATION_FIREWALL_IDLE];
                        animationCurrent.Reset();

                        m_nAddParam = m_nParam;
                    }
                }

                //#if USE_GAME_TIPS
                    if (flag && (Hero.m_nLevel <= GameWorld.gameTips[Constants.TIP_FIREWALL])) {
                        GameWorld.gameTips[Constants.TIP_FIREWALL] = -1;

                        MTMCanvas.resetKeys();
                        GameMenu.strToText(StringsID.nStrID_TipFirewall, true);
                        MTMCanvas.nCurrentGameState = MTMCanvas.GAME_STATE_SHOW_TIP;
                        GameMenu.Init(canv);
                    }
                //#endif
            break;
            }

            case ObjID.nObjID_Cannon:
                int phase = m_nParam >> 8;
                if ((phase == c_bCannonState_ClimbIn) || (phase == c_bCannonState_ClimbOut)) {
                    animationCurrent.Tick();

                    if ((animationCurrent.nStateFlg & Animation.cnANIM_STATE_END_OF_CYCLE) != 0) {
                        animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PAUSED;
                        animationCurrent.SetLastFrame();
                    }
                }
                else if(phase == c_bCannonState_Aiming) {
                    animationCurrent.Tick();
                }
                else if(phase == c_bCannonState_Fire) {
                    animationList[Constants.ANIMATION_CANNON_FIRE].Tick();
                }
            break;

            //#if USE_GAME_TIPS
                case ObjID.nObjID_Spring:
                    if (flag && (Hero.m_nLevel <= GameWorld.gameTips[Constants.TIP_SPRING])) {
                        GameWorld.gameTips[Constants.TIP_SPRING] = -1;

                        MTMCanvas.resetKeys();
                        GameMenu.strToText(StringsID.nStrID_TipSpring, true);
                        MTMCanvas.nCurrentGameState = MTMCanvas.GAME_STATE_SHOW_TIP;
                        GameMenu.Init(canv);
                    }
                break;

                case ObjID.nObjID_Teleport:
                    if (flag && (Hero.m_nLevel <= GameWorld.gameTips[Constants.TIP_TELEPORT])) {
                        GameWorld.gameTips[Constants.TIP_TELEPORT] = -1;

                        MTMCanvas.resetKeys();
                        GameMenu.strToText(StringsID.nStrID_TipTeleport, true);
                        MTMCanvas.nCurrentGameState = MTMCanvas.GAME_STATE_SHOW_TIP;
                        GameMenu.Init(canv);
                    }
                break;
            //#endif

            //#if !(IMGGROUP_12x12xLimited || IMGGROUP_24x24xLimited)
                case ObjID.nObjID_DynCount + DecID.nDecID_Torch:
                    animationCurrent.Tick();
                break;
            //#endif
        }
        return 0;
    }

    /**
     *
     */
    public boolean IsIntersect( int left, int top, int right, int bottom ) {
        switch ( nClassID ) {
            case ObjID.nObjID_CrashingPlatform: {
                int hw = PicDrawer.GetPicWidth( PicID.nPicID_crash_pf2 ) >> 1;
                int h = PicDrawer.GetPicHeight( PicID.nPicID_crash_pf2 );
                int n_obj_left = objPosX - hw;
                int n_obj_right = objPosX + hw;

                if ((objState != Constants.CRASHING_PLATFORM_STATE_CLIMB) && (objState != Constants.CRASHING_PLATFORM_STATE_WAIT)) {
                    int tmpStepY = objStepY / Constants.CRASHING_PLATFORM_STEP_DIV;
                    return ((((n_obj_left <= right) && (left <= n_obj_right))) && ((((objPosY+tmpStepY) <= bottom) && (bottom <= (objPosY+h+tmpStepY)))));
                }
                else {
                    return ((((n_obj_left <= right) && (left <= n_obj_right))) && (((objPosY <= bottom) && (bottom <= (objPosY+h)))));
                }
            }

            case ObjID.nObjID_Cannon: {
                int hw = animationCurrent.GetCurFrmWidth() >> 1;
                int n_obj_left = m_nPosX - hw;
                int n_obj_right = m_nPosX + hw;

                return ((((n_obj_left <= right) && (left <= n_obj_right))) && (((m_nPosY <= bottom) && (top <= m_nPosY))));
            }

            case ObjID.nObjID_Teleport: {
                //#if (SCREENGROUP_128x128xSpecial || SCREENGROUP_128x160xSpecial)
                    int hw = PicDrawer.GetPicWidth( PicID.nPicID_teleport1 ) >> 3;
                    int h = PicDrawer.GetPicHeight( PicID.nPicID_teleport1 );
                //#else
                    int hw = PicDrawer.GetPicWidth( PicID.nPicID_teleporter ) >> 3;
                    int h = PicDrawer.GetPicHeight( PicID.nPicID_teleporter );
                //#endif
                int n_obj_left = m_nPosX - hw;
                int n_obj_right = m_nPosX + hw;
                int n_obj_top = m_nPosY - h;

                return ((((n_obj_left <= right) && (left <= n_obj_right))) && (((n_obj_top <= bottom) && (top <= m_nPosY))));
            }

            case ObjID.nObjID_Bonus: {
                int hw = animationCurrent.GetCurFrmWidth() >> 1;
                int hh = animationCurrent.GetCurFrmHeight() >> 1;
                int n_obj_left = m_nPosX - hw;
                int n_obj_right = m_nPosX + hw;
                int n_obj_top = m_nPosY - hh;
                int n_obj_bottom = m_nPosY + hh;

                return ((((n_obj_left <= right) && (left <= n_obj_right))) && (((n_obj_top <= bottom) && (top <= n_obj_bottom))));
            }

            case ObjID.nObjID_Spring:
            case ObjID.nObjID_Firewall: {
                int hw = animationCurrent.GetCurFrmWidth() >> 1;
                int h = animationCurrent.GetCurFrmHeight();
                int n_obj_left = m_nPosX - hw;
                int n_obj_right = m_nPosX + hw;
                int n_obj_top = m_nPosY - h;

                return ((((n_obj_left <= right) && (left <= n_obj_right))) && (((n_obj_top <= bottom) && (top <= m_nPosY))));
            }

            case ObjID.nObjID_TransporterHorz:
            case ObjID.nObjID_TransporterVert:
            case ObjID.nObjID_Transporter45Degree: {
                int hw = PicDrawer.GetPicWidth( PicID.nPicID_transp1 ) >> 1;
                int h = PicDrawer.GetPicHeight( PicID.nPicID_transp1 );
                int n_obj_left = objPosX - hw;
                int n_obj_right = objPosX + hw;

                if (objState != Constants.TRANSPORTER_STATE_WAIT) {
                    return ((((n_obj_left <= right) && (left <= n_obj_right))) && ((((objPosY+objStepY) <= bottom) && (bottom <= (objPosY+h+objStepY)))));
                }
                else {
                    return ((((n_obj_left <= right) && (left <= n_obj_right))) && (((objPosY <= bottom) && (bottom <= (objPosY+h)))));
                }
            }

            case ObjID.nObjID_Ladder: {
                int hw = PicDrawer.GetPicWidth( PicID.nPicID_ladder_tile_full ) >> 1;
                int n_obj_left = m_nPosX - hw;
                int n_obj_right = m_nPosX + hw;
                int n_obj_top = m_nPosY - 1;

                return ((((n_obj_left <= right) && (left <= n_obj_right))) && (((n_obj_top <= bottom) && (top <= m_nParam))));
            }

            case ObjID.nObjID_Slide: {
                int neck = (PicDrawer.GetPicWidth( PicID.nPicID_slide_vt ) >> 1) - 2;
                int posX;

                if (m_nAddParam == m_nPosX) {
                    posX = m_nPosX;
                }
                else if (m_nAddParam < m_nPosX) {
                    posX = m_nPosX + (PicDrawer.GetPicWidth( PicID.nPicID_slide_l_t ) >> 1) - neck;
                }
                else {
                    posX = m_nPosX - (PicDrawer.GetPicWidth( PicID.nPicID_slide_r_t ) >> 1) + neck;
                }

                int n_obj_left = posX - 1;
                int n_obj_right = posX + 1;
                int n_obj_top = m_nPosY - PicDrawer.GetPicHeight( PicID.nPicID_slide_t );

                return ((((n_obj_left <= right) && (left <= n_obj_right))) && (((n_obj_top <= bottom) && (top <= m_nPosY))));
            }
        }
        return false;
    }

   /**
    *
    */
    public void Draw(Graphics g, int n_scr_x, int n_scr_y) {
        int n_scr_w = (n_scr_x + MTMCanvas.width);
        int n_scr_h = (n_scr_y + MTMCanvas.height);

        switch (nClassID) {
            case ObjID.nObjID_Bonus:
                if (m_blActive) {
                    int hw = animationCurrent.GetCurFrmWidth() >> 1;
                    int hh = animationCurrent.GetCurFrmHeight() >> 1;
                    int left = m_nPosX - hw;
                    int right = m_nPosX + hw;
                    int top = m_nPosY - hh;
                    int bottom = m_nPosY + hh;

                    if ((right >= n_scr_x) && (left <= n_scr_w) && (bottom >= n_scr_y) && (top <= n_scr_h)) {
                        animationCurrent.Draw(g, m_nPosX - n_scr_x, m_nPosY - n_scr_y);
                    }
                }
            break;

            case ObjID.nObjID_Teleport: {
                int picIndex = PicDrawer.getTeleportNumberPicIndex(teleportCount);
                animationCurrent.setLayerProperty(0, 1, Constants.LAYERPROPERTY_PIC_INDEX, picIndex);
                animationCurrent.setLayerProperty(0, 1, Constants.LAYERPROPERTY_OFFSET_X, -(PicDrawer.GetPicWidth(picIndex) >> 1));
                teleportCount++;
            }

            case ObjID.nObjID_Spring:
            case ObjID.nObjID_Firewall: {
                int hw = animationCurrent.GetCurFrmWidth() >> 1;
                int left = m_nPosX - hw;
                int right = m_nPosX + hw;
                int top = m_nPosY - animationCurrent.GetCurFrmHeight();
                if ((right >= n_scr_x) && (left <= n_scr_w) && (m_nPosY >= n_scr_y) && (top <= n_scr_h)) {
                    animationCurrent.Draw(g, m_nPosX - n_scr_x, m_nPosY - n_scr_y);
                }
            }
            break;

            case ObjID.nObjID_Cannon: {
                int hw = animationList[Constants.ANIMATION_CANNON_CLIMB].GetAnimWidth() >> 1;
                int left = m_nPosX - hw;
                int right = m_nPosX + hw;
                int top = m_nPosY - animationList[Constants.ANIMATION_CANNON_CLIMB].GetAnimHeight();
                if ((right >= n_scr_x) && (left <= n_scr_w) && (m_nPosY >= n_scr_y) && (top <= n_scr_h)) {
                    // draw the strength value if cannon in active mode
                    if (m_blActive) {
                        int n_pow = (m_nParam & 0xff);

                        int mh = PicDrawer.GetPicHeight(PicID.nPicID_canon_meter);
                        int mw = PicDrawer.GetPicWidth(PicID.nPicID_canon_meter);
                        int x = m_nPosX + hw - n_scr_x;
                        int y = m_nPosY - n_pow * mh / 5 - n_scr_y;
                        if ( n_pow != 5 ) y--;

                        PicDrawer.DrawPic( g, x, y, mw, m_nPosY - n_scr_y - y, PicID.nPicID_canon_meter, Graphics.LEFT | Graphics.TOP);
                    }

                    // draw the cannon
                    int phase = ( m_nParam >> 8 );
                    if (phase == c_bCannonState_Fire) {
                        animationCurrent.DrawAfter(g, m_nPosX - n_scr_x, m_nPosY - n_scr_y, animationList[Constants.ANIMATION_CANNON_FIRE], null);
                    }
                    else {
                        animationCurrent.Draw(g, m_nPosX - n_scr_x, m_nPosY - n_scr_y);
                    }
                }
            }
            break;

            case ObjID.nObjID_CrashingPlatform:
            case ObjID.nObjID_TransporterHorz:
            case ObjID.nObjID_TransporterVert:
            case ObjID.nObjID_Transporter45Degree: {
                int hw = animationCurrent.GetCurFrmWidth() >> 1;
                int left = objPosX - hw;
                int right = objPosX + hw;
                int bottom = objPosY + animationCurrent.GetCurFrmHeight();
                if ((right >= n_scr_x) && (left <= n_scr_w) && (bottom >= n_scr_y) && (objPosY <= n_scr_h)) {
                    animationCurrent.Draw(g, objPosX - n_scr_x, objPosY - n_scr_y);
                }
            }
            break;

            case ObjID.nObjID_Ladder: {
                int lh = PicDrawer.GetPicHeight(PicID.nPicID_ladder_tile_full);
                int lw = PicDrawer.GetPicWidth(PicID.nPicID_ladder_tile_full);
                int hw = lw >> 1;
                int x = m_nPosX;
                int y = m_nParam;
                int left = m_nPosX - hw;
                int right = m_nPosX + hw;

                // bottom
                //#if IMGGROUP_12x12xLimited
                    int tile_type = PicID.nPicID_ladder_tile_full;
                //#else
                    int tile_type = GameWorld.isFullTile(x - hw, y, x + hw, y + lh, true);
                //#endif

                if (tile_type != PicID.nPicID_ladder_tile_full) {
                    //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                        y += 3;
                    //#elif IMGGROUP_18x18
                        y += 5;
                    //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                        y += 7;
                    //#elif IMGGROUP_36x36
                        y += 10;
                    //#endif
                }

                if ((right >= n_scr_x) && (left <= n_scr_w) && (y >= n_scr_y) && ((y - lh) <= n_scr_h)) {
                    PicDrawer.DrawPic(g, x - n_scr_x, y - n_scr_y, lw, lh, tile_type, Graphics.HCENTER | Graphics.BOTTOM);
                }
            
                // body
                for (y-= lh; y > m_nPosY; y-= lh) {
                    if ((right >= n_scr_x) && (left <= n_scr_w) && (y >= n_scr_y) && ((y - lh) <= n_scr_h)) {
                        if (y - lh < m_nPosY) {
                            lh = y - m_nPosY;
                            y -= lh;
                            PicDrawer.DrawPic(g, x - n_scr_x, y - n_scr_y, lw, lh, PicID.nPicID_ladder_tile_full, Graphics.HCENTER | Graphics.TOP);
                        }
                        else {
                            PicDrawer.DrawPic(g, x - n_scr_x, y - n_scr_y, lw, lh, PicID.nPicID_ladder_tile_full, Graphics.HCENTER | Graphics.BOTTOM);
                        }
                    }
                }
            }
            break;
         
            case ObjID.nObjID_Slide: {
                int th = PicDrawer.GetPicHeight(PicID.nPicID_slide_t);
                int tw = PicDrawer.GetPicWidth(PicID.nPicID_slide_t);
                int hw = 0;
                int neck = 0;

                //#if IMGGROUP_12x12xLimited
                    int transpPic;
                //#else
                    int solidPic, transpPic;
                //#endif
                int lh, lw;
                int x, y;

                if (m_nAddParam == m_nPosX) {
                    //#if !IMGGROUP_12x12xLimited
                        solidPic = PicID.nPicID_slide_v;
                    //#endif
                    transpPic = PicID.nPicID_slide_vt;
                }
                else if (m_nAddParam < m_nPosX) {
                    //#if !IMGGROUP_12x12xLimited
                        solidPic = PicID.nPicID_slide_l;
                    //#endif
                    transpPic = PicID.nPicID_slide_l_t;
                }
                else {
                    //#if !IMGGROUP_12x12xLimited
                        solidPic = PicID.nPicID_slide_r;
                    //#endif
                    transpPic = PicID.nPicID_slide_r_t;
                }

                lw = PicDrawer.GetPicWidth(transpPic);
                lh = PicDrawer.GetPicHeight(transpPic);

                if (m_nAddParam < m_nPosX) {
                    //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                        hw = - ((lw >> 1) - 1);
                        neck = - ((PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 1);
                    //#elif IMGGROUP_18x18
                        hw = - ((lw >> 1) - 1);
                        neck = - ((PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 2);
                    //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                        hw = - ((lw >> 1) - 2);
                        neck = - ((PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 3);
                    //#elif IMGGROUP_36x36
                        hw = - ((lw >> 1) - 3);
                        neck = - ((PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 4);
                    //#endif
                }
                else if (m_nAddParam > m_nPosX) {
                    //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                        hw = (lw >> 1) - 1;
                        neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 1;
                    //#elif IMGGROUP_18x18
                        hw = (lw >> 1) - 1;
                        neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 2;
                    //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                        hw = (lw >> 1) - 2;
                        neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 3;
                    //#elif IMGGROUP_36x36
                        hw = (lw >> 1) - 3;
                        neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 4;
                    //#endif
                }

                // body
                x = m_nPosX;
                for (y = m_nPosY; y < m_nParam; y+= lh, x+= hw) {
                    if (((x + lw) >= n_scr_x) && ((x - lw) <= n_scr_w) && ((y + lh) >= n_scr_y) && (y <= n_scr_h)) {
                        //#if !IMGGROUP_12x12xLimited
                            if (GameWorld.isFullTile(x, y, x + lw, y + lh, false) == PicID.nPicID_ladder_tile_full)
                                PicDrawer.DrawPic(g, x - n_scr_x, y - n_scr_y, lw, lh, solidPic, Graphics.HCENTER | Graphics.TOP);
                            else
                        //#endif
                        PicDrawer.DrawPic(g, x - n_scr_x, y - n_scr_y, lw, lh, transpPic, Graphics.HCENTER | Graphics.TOP);
                    }
                }

                // top
                x = m_nPosX - hw + neck;
                y = m_nPosY;
                if (((x + tw) >= n_scr_x) && ((x - tw) <= n_scr_w) && (y >= n_scr_y) && ((y - th) <= n_scr_h)) {
                    PicDrawer.DrawPic(g, x - n_scr_x, y - n_scr_y, tw, th, PicID.nPicID_slide_t, Graphics.HCENTER | Graphics.BOTTOM);
                }

                // bottom
                x = m_nAddParam + hw - neck;
                y = m_nParam;
                if (((x + tw) >= n_scr_x) && ((x - tw) <= n_scr_w) && ((y + th) >= n_scr_y) && (y <= n_scr_h)) {
                    PicDrawer.DrawPic(g, x - n_scr_x, y - n_scr_y, tw, th, PicID.nPicID_slide_t, Graphics.HCENTER | Graphics.TOP);
                }
            }
            break;

            //#if !(IMGGROUP_12x12xLimited || IMGGROUP_24x24xLimited)
                case ObjID.nObjID_DynCount + DecID.nDecID_Torch: {
                    int right = m_nPosX + animationCurrent.GetCurFrmWidth();
                    int bottom = m_nPosY + animationCurrent.GetCurFrmHeight();
                    if ((right >= n_scr_x) && (m_nPosX <= n_scr_w) && (bottom >= n_scr_y) && (m_nPosY <= n_scr_h)) {
                        animationCurrent.Draw(g, m_nPosX - n_scr_x, m_nPosY - n_scr_y);
                    }
                }
                break;
            //#endif
        }
    }
}
